/*
 * @Author       : wfl
 * @LastEditors  : wfl
 * @description  :
 * @updateInfo   :
 * @Date         : 2023-11-07 19:28:12
 * @LastEditTime : 2024-01-05 12:10:13
 */
import { Config } from '@midwayjs/decorator';
import { Context } from 'vm';
import { Post, Provide, Body, Get, Query } from '@midwayjs/decorator';
import { CoolController, BaseController, RESCODE } from '@cool-midway/core';
import { ScreenDataBaseEntity } from '../../entity/base';
import { ScreenDataBaseService } from '../../service/base';
import { DataSource } from 'typeorm';
import * as jwt from 'jsonwebtoken';
/**
 * 数据库-基本信息
 */
@Provide()
@CoolController({
  api: ['add', 'delete', 'update', 'info', 'list', 'page'],
  entity: ScreenDataBaseEntity,
  service: ScreenDataBaseService,
  listQueryOp: {
    fieldEq: ['version', 'userId'],
    keyWordLikeFields: ['depId'],
  },
  before: ctx => {
    if (
      ['/admin/database/base/lists', '/admin/database/base/page'].includes(
        ctx.request.url
      )
    ) {
      ctx.request.body = {
        depId: ctx.admin.depId,
        ...ctx.request.body,
      };
    }
  },
  // 新增的时候插入当前用户ID
  insertParam: async (ctx: Context) => {
    return {
      userId: ctx.admin.userId,
      depId: ctx.admin.depId,
    };
  },
})
export class DatabaseController extends BaseController {
  async createConnect(body) {
    const dataSource = new DataSource(body);
    await dataSource.initialize();

    return {
      dataSource,
      destroy: function () {
        dataSource.destroy();
      },
    };
  }

  @Post('/test/connection')
  async testConnect(@Body() body) {
    const { dataSource, destroy } = await this.createConnect(body);
    const connectioning = dataSource.isConnected;
    destroy();
    return connectioning ? this.ok() : this.fail();
  }

  @Post('/execute/sql')
  async executeSQL(
    @Body() body: { base: string; sql: string; table?: string }
  ) {
    try {
      const DB = await (this.service as any).queryBasesId(body.base);
      const con: any = {
        type: DB.type,
        host: DB.host,
        port: DB.port,
        username: DB.username,
        password: DB.password,
      };
      if (body.table) {
        con.database = body.table;
      }
      const { dataSource, destroy } = await this.createConnect(con);
      const res = await dataSource.query(body.sql);
      destroy();
      return res;
    } catch (error) {
      console.error('error: ', error);
      return this.fail();
    }
  }

  @Get('/bases')
  async queryBasess(@Query('id') id) {
    try {
      const DB = await (this.service as any).queryBasesId(id);
      const { dataSource, destroy } = await this.createConnect(DB);
      const dbs = await dataSource.query('SHOW DATABASES;');
      const data = dbs.map(d => ({ value: d.Database }));
      return this.ok(data);
    } catch (error) {
      return this.fail();
    }
  }
  @Post('/tables')
  async queryTables(@Body() body) {
    try {
      const DB = await (this.service as any).queryBasesId(body.id);
      const { dataSource, destroy } = await this.createConnect(DB);
      const tables = await dataSource.query(
        `SELECT table_name FROM information_schema.tables WHERE table_schema = '${body.base}';`
      );
      const reTables = tables.map(ta => ta.TABLE_NAME);
      return this.ok(reTables);
    } catch (error) {
      return this.fail();
    }
  }

  @Post('/lists')
  async databaseList(@Body() body) {
    const res = await (this.service as any).databaseList(body);
    return res ? this.ok(res) : this.fail();
  }
}
